"""
用户管理器

负责用户的创建、删除、修改、查询等操作
"""

import sys
import os
from typing import List, Optional, Dict, Any
from datetime import datetime

# 添加路径
current_dir = os.path.dirname(os.path.abspath(__file__))
parent_dir = os.path.dirname(current_dir)
operating_system_dir = os.path.join(parent_dir, "OperatingSystem")
if operating_system_dir not in sys.path:
    sys.path.insert(0, operating_system_dir)

from privilege_types import UserInfo, PREDEFINED_ROLES
from security_utils import SecurityUtils
from system_schema import SYSTEM_DATABASE_NAME


class UserManager:
    """用户管理器"""
    
    def __init__(self, database_manager):
        """
        初始化用户管理器
        
        Args:
            database_manager: 数据库管理器实例
        """
        self.database_manager = database_manager
        self.system_db = None  # 系统数据库实例
        self.users_cache = {}  # 用户信息缓存 {user_key: UserInfo}
        
        # 获取系统数据库实例
        self._initialize_system_database()
        
        # 加载用户信息到缓存
        self._load_users_cache()
    
    def _initialize_system_database(self):
        """初始化系统数据库"""
        try:
            self.system_db = self.database_manager.get_database(SYSTEM_DATABASE_NAME)
            if not self.system_db:
                # 尝试手动加载系统数据库（解决延迟加载问题）
                import os
                system_db_path = os.path.join(self.database_manager.data_root, SYSTEM_DATABASE_NAME)
                if os.path.exists(system_db_path):
                    # 手动触发延迟加载
                    success = self.database_manager._load_database_instance(SYSTEM_DATABASE_NAME)
                    if success:
                        self.system_db = self.database_manager.get_database(SYSTEM_DATABASE_NAME)
                        if self.system_db:
                            print(f"[UserManager] 通过手动加载成功获取system数据库")
                        else:
                            raise RuntimeError(f"Manual loading succeeded but still cannot get system database")
                    else:
                        raise RuntimeError(f"Failed to manually load system database from {system_db_path}")
                else:
                    raise RuntimeError(f"System database directory not found: {system_db_path}")
            
            if not self.system_db:
                raise RuntimeError(f"System database '{SYSTEM_DATABASE_NAME}' not found after all attempts")
                
        except Exception as e:
            raise RuntimeError(f"Failed to initialize system database: {e}")
    
    def _load_users_cache(self):
        """从系统表加载用户信息到缓存"""
        try:
            # 查询所有用户
            users_records = self.system_db.select_records("users")
            
            self.users_cache = {}
            for record in users_records:
                user_info = UserInfo(
                    username=record["username"],
                    host=record["host"],
                    password_hash=record["password_hash"],
                    created_time=datetime.fromisoformat(record["created_time"]) if isinstance(record["created_time"], str) else record["created_time"],
                    last_login=datetime.fromisoformat(record["last_login"]) if record["last_login"] and isinstance(record["last_login"], str) else record["last_login"],
                    is_active=record["is_active"],
                    max_connections=record["max_connections"]
                )
                
                self.users_cache[user_info.get_user_key()] = user_info
                
        except Exception as e:
            # 如果加载失败（可能是首次启动），清空缓存
            self.users_cache = {}
    
    def create_user(self, username: str, password: str, host: str = '%', 
                   max_connections: int = 100, created_by: str = 'system') -> bool:
        """
        创建用户
        
        Args:
            username: 用户名
            password: 密码
            host: 主机
            max_connections: 最大连接数
            created_by: 创建者
            
        Returns:
            bool: 创建是否成功
        """
        try:
            # 验证输入
            if not SecurityUtils.is_valid_username(username):
                raise ValueError(f"Invalid username: {username}")
            
            if not SecurityUtils.is_valid_host(host):
                raise ValueError(f"Invalid host: {host}")
            
            is_strong, reason = SecurityUtils.is_strong_password(password)
            if not is_strong:
                raise ValueError(f"Password not strong enough: {reason}")
            
            user_key = f"{username}@{host}"
            
            # 检查用户是否已存在
            if user_key in self.users_cache:
                raise ValueError(f"User '{user_key}' already exists")
            
            # 创建用户信息
            password_hash = SecurityUtils.hash_password(password)
            user_info = UserInfo(
                username=username,
                host=host,
                password_hash=password_hash,
                created_time=datetime.now(),
                is_active=True,
                max_connections=max_connections
            )
            
            # 生成用户ID（简化实现：使用哈希）
            user_id = hash(f"{username}@{host}") % 1000000  # 限制在1M内
            
            # 插入到系统表
            user_record = {
                "user_id": user_id,
                "username": username,
                "host": host,
                "password_hash": password_hash,
                "created_time": user_info.created_time,
                "last_login": None,
                "is_active": True,
                "max_connections": max_connections
            }
            
            success = self.system_db.insert_record("users", user_record)
            if success:
                # 更新缓存
                self.users_cache[user_key] = user_info
                return True
            else:
                raise RuntimeError("Failed to insert user record")
                
        except Exception as e:
            print(f"Error creating user {username}@{host}: {e}")
            return False
    
    def drop_user(self, username: str, host: str = '%') -> bool:
        """
        删除用户
        
        Args:
            username: 用户名
            host: 主机
            
        Returns:
            bool: 删除是否成功
        """
        try:
            user_key = f"{username}@{host}"
            
            # 检查用户是否存在
            if user_key not in self.users_cache:
                raise ValueError(f"User '{user_key}' does not exist")
            
            # 不能删除root用户
            if username == 'root':
                raise ValueError("Cannot drop root user")
            
            # 从系统表删除
            condition = {"username": username, "host": host}
            deleted_count = self.system_db.delete_records("users", condition)
            
            if deleted_count > 0:
                # 从缓存删除
                del self.users_cache[user_key]
                
                # 同时删除用户的所有权限
                self._cleanup_user_privileges(username, host)
                
                return True
            else:
                raise RuntimeError("Failed to delete user record")
                
        except Exception as e:
            print(f"Error dropping user {username}@{host}: {e}")
            return False
    
    def change_password(self, username: str, new_password: str, host: str = '%') -> bool:
        """
        修改用户密码
        
        Args:
            username: 用户名
            new_password: 新密码
            host: 主机
            
        Returns:
            bool: 修改是否成功
        """
        try:
            user_key = f"{username}@{host}"
            
            # 检查用户是否存在
            if user_key not in self.users_cache:
                raise ValueError(f"User '{user_key}' does not exist")
            
            # 检查密码强度
            is_strong, reason = SecurityUtils.is_strong_password(new_password)
            if not is_strong:
                raise ValueError(f"Password not strong enough: {reason}")
            
            # 生成新密码哈希
            new_password_hash = SecurityUtils.hash_password(new_password)
            
            # 更新系统表
            condition = {"username": username, "host": host}
            updates = {"password_hash": new_password_hash}
            updated_count = self.system_db.update_records("users", condition, updates)
            
            if updated_count > 0:
                # 更新缓存
                user_info = self.users_cache[user_key]
                user_info.password_hash = new_password_hash
                
                return True
            else:
                raise RuntimeError("Failed to update password")
                
        except Exception as e:
            print(f"Error changing password for {username}@{host}: {e}")
            return False
    
    def authenticate_user(self, username: str, password: str, host: str = '%') -> Optional[UserInfo]:
        """
        验证用户身份
        
        Args:
            username: 用户名
            password: 密码
            host: 主机
            
        Returns:
            Optional[UserInfo]: 验证成功返回用户信息，否则返回None
        """
        try:
            # 首先尝试精确匹配
            user_key = f"{username}@{host}"
            user_info = self.users_cache.get(user_key)
            
            # 如果精确匹配失败，尝试通配符匹配
            if not user_info:
                wildcard_key = f"{username}@%"
                user_info = self.users_cache.get(wildcard_key)
            
            if not user_info:
                return None
            
            # 检查用户是否激活
            if not user_info.is_active:
                return None
            
            # 验证密码
            if SecurityUtils.verify_password(password, user_info.password_hash):
                # 更新最后登录时间
                self._update_last_login(username, user_info.host)
                return user_info
            
            return None
            
        except Exception as e:
            print(f"Error authenticating user {username}@{host}: {e}")
            return None
    
    def get_user_info(self, username: str, host: str = '%') -> Optional[UserInfo]:
        """
        获取用户信息
        
        Args:
            username: 用户名
            host: 主机
            
        Returns:
            Optional[UserInfo]: 用户信息
        """
        user_key = f"{username}@{host}"
        return self.users_cache.get(user_key)
    
    def list_users(self) -> List[UserInfo]:
        """
        列出所有用户
        
        Returns:
            List[UserInfo]: 用户信息列表
        """
        return list(self.users_cache.values())
    
    def user_exists(self, username: str, host: str = '%') -> bool:
        """
        检查用户是否存在
        
        Args:
            username: 用户名
            host: 主机
            
        Returns:
            bool: 用户是否存在
        """
        user_key = f"{username}@{host}"
        
        # 首先检查缓存
        if user_key in self.users_cache:
            return True
        
        # 如果缓存中没有，检查数据库
        try:
            condition = {"username": username, "host": host}
            records = self.system_db.select_records("users", condition)
            exists = len(records) > 0
            
            # 如果用户存在，加载到缓存中
            if exists:
                print(f"[DEBUG] Loading user {username}@{host} to cache")
                self._load_user_to_cache(username, host)
            
            return exists
        except Exception as e:
            print(f"Error checking user existence for {username}@{host}: {e}")
            return False
    
    def _load_user_to_cache(self, username: str, host: str):
        """从数据库加载用户信息到缓存"""
        try:
            condition = {"username": username, "host": host}
            records = self.system_db.select_records("users", condition)
            
            if records:
                record = records[0]  # 取第一条记录
                user_info = UserInfo(
                    username=record.get("username"),
                    password_hash=record.get("password_hash"),
                    host=record.get("host"),
                    created_time=record.get("created_time"),
                    last_login=record.get("last_login"),
                    is_active=record.get("is_active", True),
                    max_connections=record.get("max_connections", 10)
                )
                user_key = f"{username}@{host}"
                self.users_cache[user_key] = user_info
        except Exception as e:
            print(f"Error loading user {username}@{host} to cache: {e}")
    
    def set_user_active(self, username: str, host: str, is_active: bool) -> bool:
        """
        设置用户状态
        
        Args:
            username: 用户名
            host: 主机
            is_active: 是否激活
            
        Returns:
            bool: 设置是否成功
        """
        try:
            user_key = f"{username}@{host}"
            
            if user_key not in self.users_cache:
                return False
            
            # 更新系统表
            condition = {"username": username, "host": host}
            updates = {"is_active": is_active}
            updated_count = self.system_db.update_records("users", condition, updates)
            
            if updated_count > 0:
                # 更新缓存
                self.users_cache[user_key].is_active = is_active
                return True
            
            return False
            
        except Exception as e:
            print(f"Error setting user active status for {username}@{host}: {e}")
            return False
    
    def _update_last_login(self, username: str, host: str):
        """更新用户最后登录时间"""
        try:
            condition = {"username": username, "host": host}
            updates = {"last_login": datetime.now()}
            self.system_db.update_records("users", condition, updates)
            
            # 更新缓存
            user_key = f"{username}@{host}"
            if user_key in self.users_cache:
                self.users_cache[user_key].last_login = datetime.now()
                
        except Exception as e:
            print(f"Warning: Failed to update last login time for {username}@{host}: {e}")
    
    def _cleanup_user_privileges(self, username: str, host: str):
        """清理用户的所有权限"""
        try:
            condition = {"username": username, "host": host}
            
            # 删除全局权限
            self.system_db.delete_records("global_privs", condition)
            
            # 删除数据库权限
            self.system_db.delete_records("db_privs", condition)
            
            # 删除表权限
            self.system_db.delete_records("table_privs", condition)
            
            # 删除列权限
            self.system_db.delete_records("column_privs", condition)
            
            # 删除角色关系
            self.system_db.delete_records("user_roles", condition)
            
        except Exception as e:
            print(f"Warning: Failed to cleanup privileges for {username}@{host}: {e}")
    
    def create_default_root_user(self, password: str = "root12345") -> bool:
        """
        创建默认root用户
        
        Args:
            password: root密码
            
        Returns:
            bool: 创建是否成功
        """
        try:
            if self.user_exists("root", "%"):
                return True  # root用户已存在
            
            # 创建root用户
            success = self.create_user("root", password, "%", max_connections=1000, created_by="system")
            if success:
                print("Created default root user")
            
            return success
            
        except Exception as e:
            print(f"Error creating default root user: {e}")
            return False
    
    def get_user_statistics(self) -> Dict[str, Any]:
        """
        获取用户统计信息
        
        Returns:
            Dict[str, Any]: 统计信息
        """
        total_users = len(self.users_cache)
        active_users = sum(1 for user in self.users_cache.values() if user.is_active)
        inactive_users = total_users - active_users
        
        return {
            "total_users": total_users,
            "active_users": active_users,
            "inactive_users": inactive_users,
            "users_by_host": self._get_users_by_host_stats()
        }
    
    def _get_users_by_host_stats(self) -> Dict[str, int]:
        """获取按主机分组的用户统计"""
        host_stats = {}
        for user in self.users_cache.values():
            host = user.host
            host_stats[host] = host_stats.get(host, 0) + 1
        return host_stats
